/* operand halt (0) */
case 0:
#ifdef JS_RUNTIME_WARNING
sprintf(buf, "VM: halt%s", JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
js_iostream_write(vm->s_stderr, buf, strlen(buf));
js_iostream_flush(vm->s_stderr);
#else
fwrite(buf, strlen(buf), 1, stderr);
#endif
#endif
//  while (1)
//    sleep (5);
break;

/* operand done (1) */
case 1:
DONE();
break;

/* operand nop (2) */
case 2:
  /* Nothing here! */
break;

/* operand dup (3) */
case 3:
JS_COPY(JS_SP0, JS_SP1);
JS_PUSH();
break;

/* operand pop (4) */
case 4:
JS_POP();
break;

/* operand pop_n (5) */
case 5:
READ_INT8(i);
JS_POP_N(i);
break;

/* operand apop (6) */
case 6:
READ_INT8(i);
JS_COPY(JS_SP(i + 1), JS_SP1);
JS_POP_N(i);
break;

/* operand swap (7) */
case 7:
JS_COPY(JS_SP0, JS_SP2);
JS_COPY(JS_SP2, JS_SP1);
JS_COPY(JS_SP1, JS_SP0);
break;

/* operand roll (8) */
case 8:
READ_INT8(i8);

if (i8 > 1) {
    int j;

    for (j = 0; j < i8; j++)
        JS_COPY(JS_SP(j), JS_SP(j + 1));

    JS_COPY(JS_SP(i8), JS_SP0);
} else if (i8 < -1) {
    i8 = -i8;

    JS_COPY(JS_SP0, JS_SP(i8));
    for (; i8 > 0; i8--)
        JS_COPY(JS_SP(i8), JS_SP(i8 - 1));
}
break;

/* operand const (9) */
case 9:
READ_INT32(i);
JS_COPY(JS_SP0, JS_CONST(i));
JS_PUSH();
break;

/* operand const_null (10) */
case 10:
JS_SP0->type = JS_NULL;
JS_PUSH();
break;

/* operand const_true (11) */
case 11:
JS_SP0->type = JS_BOOLEAN;
JS_SP0->u.vboolean = 1;
JS_PUSH();
break;

/* operand const_false (12) */
case 12:
JS_SP0->type = JS_BOOLEAN;
JS_SP0->u.vboolean = 0;
JS_PUSH();
break;

/* operand const_undefined (13) */
case 13:
JS_SP0->type = JS_UNDEFINED;
JS_PUSH();
break;

/* operand const_i0 (14) */
case 14:
JS_SP0->type = JS_INTEGER;
JS_SP0->u.vinteger = 0;
JS_PUSH();
break;

/* operand const_i1 (15) */
case 15:
JS_SP0->type = JS_INTEGER;
JS_SP0->u.vinteger = 1;
JS_PUSH();
break;

/* operand const_i2 (16) */
case 16:
JS_SP0->type = JS_INTEGER;
JS_SP0->u.vinteger = 2;
JS_PUSH();
break;

/* operand const_i3 (17) */
case 17:
JS_SP0->type = JS_INTEGER;
JS_SP0->u.vinteger = 3;
JS_PUSH();
break;

/* operand const_i (18) */
case 18:
READ_INT32(i);
JS_SP0->type = JS_INTEGER;
JS_SP0->u.vinteger = i;
JS_PUSH();
break;

/* operand load_global (19) */
case 19:
READ_INT32(j);

  /* Use the global value only. */
JS_COPY(JS_SP0, JS_GLOBAL(j));
JS_PUSH();

#ifdef JS_RUNTIME_WARNING
if (vm->warn_undef && JS_SP1->type == JS_UNDEFINED) {
    sprintf(buf, "VM: warning: using undefined global `%s'%s",
            js_vm_symname(vm, j), JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
	js_iostream_write(vm->s_stderr, buf, strlen(buf));
#else
	fwrite(buf, strlen(buf), 1, stderr);
#endif
}
#endif

break;

/* operand store_global (20) */
case 20:
READ_INT32(i);

  /* Operand store_global do not check the with-chain. */
  /* WITHCHAIN */

  /* Set the global value. */
JS_COPY(JS_GLOBAL(i), JS_SP1);
JS_POP();
break;

/* operand load_arg (21) */
case 21:
READ_INT8(i);
JS_COPY(JS_SP0, JS_ARG(i));
JS_PUSH();
break;

/* operand store_arg (22) */
case 22:
READ_INT8(i);
JS_COPY(JS_ARG(i), JS_SP1);
JS_POP();
break;

/* operand load_local (23) */
case 23:
READ_INT16(i);
JS_COPY(JS_SP0, JS_LOCAL(i));
JS_PUSH();
break;

/* operand store_local (24) */
case 24:
READ_INT16(i);
JS_COPY(JS_LOCAL(i), JS_SP1);
JS_POP();
break;

/* operand load_property (25) */
case 25:
  /* Fetch the property symbol. */
READ_INT32(j);

if (JS_SP1->type == JS_BUILTIN) {
    JS_SAVE_REGS();
    if (JS_SP1->u.vbuiltin->info->property_proc) {
        if ((*JS_SP1->u.vbuiltin->info->property_proc) (vm,
                                                        JS_SP1->u.
                                                        vbuiltin->info,
                                                        JS_SP1->u.
                                                        vbuiltin->
                                                        instance_context,
                                                        j, 0,
                                                        &builtin_result)
            == JS_PROPERTY_UNKNOWN) {
            if (j == vm->syms.s_prototype) {
                /* Looking up the prototype. */

                builtin_result.type = JS_OBJECT;
                if (JS_SP1->u.vbuiltin->prototype)
                    /* This is an instance. */
                    builtin_result.u.vobject =
                        JS_SP1->u.vbuiltin->prototype;
                else
                    /* This is a class. */
                    builtin_result.u.vobject
                        = JS_SP1->u.vbuiltin->info->prototype;
            } else {
                /* Looking up stuffs from the prototype. */

                if (JS_SP1->u.vbuiltin->prototype)
                    /* An instance. */
                    js_vm_object_load_property(vm,
                                               JS_SP1->u.vbuiltin->
                                               prototype, j,
                                               &builtin_result);
                else
                    /* A class. */
                    js_vm_object_load_property(vm,
                                               JS_SP1->u.vbuiltin->info->
                                               prototype, j,
                                               &builtin_result);
            }
        }
        JS_COPY(JS_SP1, &builtin_result);
    } else {
        ERROR("illegal builtin object for load_property");
	}
} else if (JS_SP1->type == JS_OBJECT) {
    js_vm_object_load_property(vm, JS_SP1->u.vobject, j, JS_SP1);
} else if (vm->prim[JS_SP1->type]) {
    /* The primitive language types. */
    JS_SAVE_REGS();
    if ((*vm->prim[JS_SP1->type]->property_proc) (vm,
                                                  vm->prim[JS_SP1->type],
                                                  JS_SP1, j, 0,
                                                  &builtin_result)
        == JS_PROPERTY_UNKNOWN) {
        if (j == vm->syms.s_prototype) {
            /* Looking up the prototype. */
            switch (JS_SP1->type) {
            case JS_STRING:
                if (JS_SP1->u.vstring->prototype) {
                    builtin_result.type = JS_OBJECT;
                    builtin_result.u.vobject =
                        JS_SP1->u.vstring->prototype;
                } else
                    /* No prototype yet. */
                    builtin_result.type = JS_NULL;
                break;

            case JS_ARRAY:
                if (JS_SP1->u.varray->prototype) {
                    builtin_result.type = JS_OBJECT;
                    builtin_result.u.vobject = JS_SP1->u.varray->prototype;
                } else
                    /* No prototype yet. */
                    builtin_result.type = JS_NULL;
                break;

            case JS_FUNC:
                if (JS_SP1->u.vfunction->prototype) {
                    builtin_result.type = JS_OBJECT;
                    builtin_result.u.vobject
                        = JS_SP1->u.vfunction->prototype;
                } else
                    /* No prototype yet. */
                    builtin_result.type = JS_NULL;
                break;

            default:
                /* The rest do not have prototype. */
                builtin_result.type = JS_NULL;
                break;
            }
        } else {
            /* Looking up stuffs from the prototype. */
            switch (JS_SP1->type) {
            case JS_STRING:
                if (JS_SP1->u.vstring->prototype)
                    js_vm_object_load_property(vm,
                                               JS_SP1->u.vstring->
                                               prototype, j,
                                               &builtin_result);
                else
                    /* Take it from the class' prototype */
                    goto _op_load_property_try_proto;
                break;

            case JS_ARRAY:
                if (JS_SP1->u.varray->prototype)
                    js_vm_object_load_property(vm,
                                               JS_SP1->u.varray->prototype,
                                               j, &builtin_result);
                else
                    /* Take it from the class' prototype */
                    goto _op_load_property_try_proto;
                break;

            case JS_FUNC:
                if (JS_SP1->u.vfunction->prototype)
                    js_vm_object_load_property(vm,
                                               JS_SP1->u.vfunction->
                                               prototype, j,
                                               &builtin_result);
                else
                    /* Take it from the class' prototype */
                    goto _op_load_property_try_proto;
                break;

            default:
                /*
                 * The rest do not have instance prototypes; use the
                 * class prototypes.
                 */
              _op_load_property_try_proto:
                js_vm_object_load_property(vm,
                                           vm->prim[JS_SP1->type]->
                                           prototype, j, &builtin_result);
                break;
            }
        }
    }

    JS_COPY(JS_SP1, &builtin_result);
} else {
    ERROR("illegal object for load_property");
}
break;

/* operand store_property (26) */
case 26:
  /* Fetch the property symbol. */
READ_INT32(j);

if (JS_SP1->type == JS_BUILTIN) {
    JS_SAVE_REGS();
    if (JS_SP1->u.vbuiltin->info->property_proc) {
        if ((*JS_SP1->u.vbuiltin->info->property_proc) (vm,
                                                        JS_SP1->u.
                                                        vbuiltin->info,
                                                        JS_SP1->u.
                                                        vbuiltin->
                                                        instance_context,
                                                        j, 1, JS_SP2)
            == JS_PROPERTY_UNKNOWN) {
            if (j == vm->syms.s_prototype) {
                /* Setting the prototype. */
                if (JS_SP2->type != JS_OBJECT) {
                    ERROR("illegal value for set_property");
				}

                if (JS_SP1->u.vbuiltin->prototype)
                    /* Setting the instance's prototype. */
                    JS_SP1->u.vbuiltin->prototype = JS_SP2->u.vobject;
                else
                    /* Setting the class' prototype. */
                    JS_SP1->u.vbuiltin->info->prototype =
                        JS_SP2->u.vobject;
            } else {
                /* Setting stuff to the prototype. */
                if (JS_SP1->u.vbuiltin->prototype)
                    /* An instance. */
                    js_vm_object_store_property(vm,
                                                JS_SP1->u.vbuiltin->
                                                prototype, j, JS_SP2);
                else
                    /* A class. */
                    js_vm_object_store_property(vm,
                                                JS_SP1->u.vbuiltin->info->
                                                prototype, j, JS_SP2);
            }
        }
    } else {
        ERROR("illegal builtin object for store_property");
	}

    JS_POP();
    JS_POP();
} else if (JS_SP1->type == JS_OBJECT) {
    js_vm_object_store_property(vm, JS_SP1->u.vobject, j, JS_SP2);
    JS_POP();
    JS_POP();
} else if (vm->prim[JS_SP1->type]) {
    /* The primitive language types. */
    JS_SAVE_REGS();
    if ((*vm->prim[JS_SP1->type]->property_proc) (vm,
                                                  vm->prim[JS_SP1->type],
                                                  JS_SP1, j, 1, JS_SP2)
        == JS_PROPERTY_UNKNOWN) {
        if (j == vm->syms.s_prototype) {
            /* Setting the prototype. */
            if (JS_SP2->type != JS_OBJECT) {
                ERROR("illegal value for set_property");
			}

            switch (JS_SP1->type) {
            case JS_STRING:
                JS_SP1->u.vstring->prototype = JS_SP2->u.vobject;
                break;

            case JS_ARRAY:
                JS_SP1->u.varray->prototype = JS_SP2->u.vobject;
                break;

            case JS_FUNC:
                JS_SP1->u.vfunction->prototype = JS_SP2->u.vobject;
                break;

            default:
                ERROR("illegal object for set_property");
                break;
            }
        } else {
            JSNode prototype;

            /* Setting to the prototype.  We create them on demand. */
            switch (JS_SP1->type) {
            case JS_STRING:
                if (JS_SP1->u.vstring->prototype == NULL) {
                    prototype.type = JS_OBJECT;

                    /* Create the prototype and set its __proto__. */
                    JS_SP1->u.vstring->prototype = js_vm_object_new(vm);
                    prototype.u.vobject = vm->prim[JS_OBJECT]->prototype;
                    js_vm_object_store_property(vm,
                                                JS_SP1->u.vstring->
                                                prototype,
                                                vm->syms.s___proto__,
                                                &prototype);
                }
                js_vm_object_store_property(vm,
                                            JS_SP1->u.vstring->prototype,
                                            j, JS_SP2);
                break;

            case JS_ARRAY:
                if (JS_SP1->u.varray->prototype == NULL) {
                    prototype.type = JS_OBJECT;

                    /* Create the prototype and set its __proto__. */
                    JS_SP1->u.varray->prototype = js_vm_object_new(vm);
                    prototype.u.vobject = vm->prim[JS_OBJECT]->prototype;
                    js_vm_object_store_property(vm,
                                                JS_SP1->u.varray->
                                                prototype,
                                                vm->syms.s___proto__,
                                                &prototype);
                }
                js_vm_object_store_property(vm,
                                            JS_SP1->u.varray->prototype,
                                            j, JS_SP2);
                break;

            case JS_FUNC:
                if (JS_SP1->u.vfunction->prototype == NULL) {
                    prototype.type = JS_OBJECT;

                    /* Create the prototype and set its __proto__. */
                    JS_SP1->u.vfunction->prototype = js_vm_object_new(vm);
                    prototype.u.vobject = vm->prim[JS_OBJECT]->prototype;
                    js_vm_object_store_property(vm,
                                                JS_SP1->u.vfunction->
                                                prototype,
                                                vm->syms.s___proto__,
                                                &prototype);
                }
                js_vm_object_store_property(vm,
                                            JS_SP1->u.vfunction->prototype,
                                            j, JS_SP2);
                break;

            default:
                ERROR("illegal object for set_property");
                break;
            }
        }
    }
    JS_POP();
    JS_POP();
} else {
    ERROR("illegal object for store_property");
}

JS_MAYBE_GC();
break;

/* operand load_array (27) */
case 27:
if (JS_SP2->type == JS_BUILTIN) {
    if (JS_SP1->type == JS_INTEGER) {
        ERROR("integer indexes not implemented yet for BUILTIN in load_array");
    } else if (JS_SP1->type == JS_STRING) {
        /* Intern the string. */
        j = js_vm_intern_with_len(vm, JS_SP1->u.vstring->data,
                                  JS_SP1->u.vstring->len);

        /* The code below must be in sync with operand `load_property'. */
        JS_SAVE_REGS();

        if (JS_SP2->u.vbuiltin->info->property_proc) {
            if ((*JS_SP2->u.vbuiltin->info->property_proc) (vm,
                                                            JS_SP2->u.
                                                            vbuiltin->info,
                                                            JS_SP2->u.
                                                            vbuiltin->
                                                            instance_context,
                                                            j, 0,
                                                            &builtin_result)
                == JS_PROPERTY_UNKNOWN) {
                if (j == vm->syms.s_prototype) {
                    /* Looking up the prototype. */

                    builtin_result.type = JS_OBJECT;
                    if (JS_SP2->u.vbuiltin->prototype)
                        /* This is an instance. */
                        builtin_result.u.vobject
                            = JS_SP2->u.vbuiltin->prototype;
                    else
                        /* This is a class. */
                        builtin_result.u.vobject
                            = JS_SP2->u.vbuiltin->info->prototype;
                } else {
                    /* Looking up stuffs from the prototype. */

                    if (JS_SP2->u.vbuiltin->prototype)
                        /* An instance. */
                        js_vm_object_load_property(vm,
                                                   JS_SP2->u.vbuiltin->
                                                   prototype, j,
                                                   &builtin_result);
                    else
                        /* A class. */
                        js_vm_object_load_property(vm,
                                                   JS_SP2->u.vbuiltin->
                                                   info->prototype, j,
                                                   &builtin_result);
                }
            }
            JS_COPY(JS_SP2, &builtin_result);
            JS_POP();
        } else {
            ERROR("illegal builtin object for load_array");
		}
    } else {
		ERROR("illegal array index in load_array (%d)", JS_SP1->type);
    }
} else if (JS_SP2->type == JS_OBJECT) {
    js_vm_object_load_array(vm, JS_SP2->u.vobject, JS_SP1, JS_SP2);
    JS_POP();
} else if (JS_SP2->type == JS_ARRAY) {
    if (JS_SP1->type == JS_INTEGER) {
        if (JS_SP1->u.vinteger < 0
            || JS_SP1->u.vinteger >= JS_SP2->u.varray->length)
            JS_SP2->type = JS_UNDEFINED;
        else {
            JSNode *n = &JS_SP2->u.varray->data[JS_SP1->u.vinteger];
            JS_COPY(JS_SP2, n);
        }
        JS_POP();
    } else {
        ERROR("illegal array index in load_array (%d)", JS_SP1->type);
    }
} else if (JS_SP2->type == JS_STRING) {
    if (JS_SP1->type == JS_INTEGER) {
        int ch;

        if (JS_SP1->u.vinteger < 0
            || JS_SP1->u.vinteger >= JS_SP2->u.vstring->len) {
            ERROR("string index out of range in load_array");
		}

        ch = JS_SP2->u.vstring->data[JS_SP1->u.vinteger];
        JS_SP2->type = JS_INTEGER;
        JS_SP2->u.vinteger = ch;

        JS_POP();
    } else {
        ERROR("illegal string index in load_array");
	}
} else {
    ERROR("illegal object for load_array");
}
break;

/* operand store_array (28) */
case 28:
if (JS_SP2->type == JS_BUILTIN) {
    if (JS_SP1->type == JS_INTEGER) {
        ERROR("integer index not implemented yet for BUILTIN in store_array");
    } else if (JS_SP1->type == JS_STRING) {
        /* Intern the string. */
        j = js_vm_intern_with_len(vm, JS_SP1->u.vstring->data,
                                  JS_SP1->u.vstring->len);

        /* The code below msut be in sync with operand `store_property'. */
        JS_SAVE_REGS();
        if (JS_SP2->u.vbuiltin->info->property_proc) {
            if ((*JS_SP2->u.vbuiltin->info->property_proc) (vm,
                                                            JS_SP2->u.
                                                            vbuiltin->info,
                                                            JS_SP2->u.
                                                            vbuiltin->
                                                            instance_context,
                                                            j, 1, JS_SP(3))
                == JS_PROPERTY_UNKNOWN) {
                if (j == vm->syms.s_prototype) {
                    /* Setting the prototype. */
                    if (JS_SP(3)->type != JS_OBJECT) {
                        ERROR("illegal value for prototype");
					}

                    if (JS_SP2->u.vbuiltin->prototype)
                        /* Setting the instance's prototype. */
                        JS_SP2->u.vbuiltin->prototype =
                            JS_SP(3)->u.vobject;
                    else
                        /* Setting the class' prototype. */
                        JS_SP2->u.vbuiltin->info->prototype
                            = JS_SP(3)->u.vobject;
                } else {
                    /* Setting stuff to the prototype. */
                    if (JS_SP2->u.vbuiltin->prototype)
                        /* An instance. */
                        js_vm_object_store_property(vm,
                                                    JS_SP2->u.vbuiltin->
                                                    prototype, j,
                                                    JS_SP(3));
                    else
                        /* A class. */
                        js_vm_object_store_property(vm,
                                                    JS_SP2->u.vbuiltin->
                                                    info->prototype, j,
                                                    JS_SP(3));
                }
            }
        } else {
            ERROR("illegal builtin object for store_array");
		}

        JS_POP_N(3);
    } else {
        ERROR("illegal array index in store_array");
	}
} else if (JS_SP2->type == JS_OBJECT) {
    js_vm_object_store_array(vm, JS_SP2->u.vobject, JS_SP1, JS_SP(3));
    JS_POP_N(3);
} else if (JS_SP2->type == JS_ARRAY) {
    if (JS_SP1->type == JS_INTEGER) {
        if (JS_SP1->u.vinteger < 0) {
            ERROR("negative array index in store_array");
		}
        if (JS_SP1->u.vinteger >= JS_SP2->u.varray->length)
            js_vm_expand_array(vm, JS_SP2, JS_SP1->u.vinteger + 1);

        JS_COPY(&JS_SP2->u.varray->data[JS_SP1->u.vinteger], JS_SP(3));
        JS_POP_N(3);
    } else {
        ERROR("illegal array index in store_array");
	}
} else if (JS_SP2->type == JS_STRING) {
    if (JS_SP1->type == JS_INTEGER) {
        if (JS_SP2->u.vstring->staticp) {
            ERROR("static string in store_array");
		}

        if (JS_SP1->u.vinteger < 0) {
            ERROR("negative string index in store_array");
		}

        if (JS_SP(3)->type != JS_INTEGER) {
            ERROR("non-integer value to store into string in store_array");
		}

        if (JS_SP1->u.vinteger >= JS_SP2->u.vstring->len) {
            /* Expand the string. */
            JS_SP2->u.vstring->data = js_vm_realloc(vm,
                                                    JS_SP2->u.vstring->
                                                    data,
                                                    JS_SP1->u.vinteger +
                                                    1);
            /* Fill the gap with ' '. */
            for (; JS_SP2->u.vstring->len <= JS_SP1->u.vinteger;)
                JS_SP2->u.vstring->data[JS_SP2->u.vstring->len++] = ' ';
        }

        JS_SP2->u.vstring->data[JS_SP1->u.vinteger]
            = (unsigned char) JS_SP(3)->u.vinteger;
        JS_POP_N(3);
    } else {
        ERROR("illegal string index in store_array");
	}
} else {
    ERROR("illegal object for store_array");
}

JS_MAYBE_GC();
break;

/* operand nth (29) */
case 29:
if (JS_SP2->type == JS_STRING) {
    if (JS_SP1->u.vinteger < 0
        || JS_SP1->u.vinteger >= JS_SP2->u.vstring->len) {
        JS_SP2->type = JS_UNDEFINED;

        JS_SP1->type = JS_BOOLEAN;
        JS_SP1->u.vboolean = 0;
    } else {
        JS_SP2->type = JS_INTEGER;
        JS_SP2->u.vinteger = JS_SP2->u.vstring->data[JS_SP1->u.vinteger];

        JS_SP1->type = JS_BOOLEAN;
        JS_SP1->u.vboolean = 1;
    }
} else if (JS_SP2->type == JS_ARRAY) {
    if (JS_SP1->u.vinteger < 0
        || JS_SP1->u.vinteger >= JS_SP2->u.varray->length) {
        JS_SP2->type = JS_UNDEFINED;

        JS_SP1->type = JS_BOOLEAN;
        JS_SP1->u.vboolean = 0;
    } else {
        JSNode *n = &JS_SP2->u.varray->data[JS_SP1->u.vinteger];
        JS_COPY(JS_SP2, n);

        JS_SP1->type = JS_BOOLEAN;
        JS_SP1->u.vboolean = 1;
    }
} else if (JS_SP2->type == JS_OBJECT) {
    i = js_vm_object_nth(vm, JS_SP2->u.vobject, JS_SP1->u.vinteger,
                         JS_SP2);
    JS_SP1->type = JS_BOOLEAN;
    JS_SP1->u.vboolean = i;
} else {
    ERROR("illegal object for nth");
}
break;

/* operand cmp_eq (30) */
case 30:
JS_OPERAND_CMP_EQ( ==, 1);
break;

/* operand cmp_ne (31) */
case 31:
JS_OPERAND_CMP_EQ(!=, 0);
break;

/* operand cmp_lt (32) */
case 32:
JS_OPERAND_CMP_REL(<);
break;

/* operand cmp_gt (33) */
case 33:
JS_OPERAND_CMP_REL(>);
break;

/* operand cmp_le (34) */
case 34:
JS_OPERAND_CMP_REL(<=);
break;

/* operand cmp_ge (35) */
case 35:
JS_OPERAND_CMP_REL(>=);
break;

/* operand cmp_seq (36) */
case 36:
JS_OPERAND_CMP_SEQ( ==, 1);
break;

/* operand cmp_sne (37) */
case 37:
JS_OPERAND_CMP_SEQ(!=, 0);
break;

/* operand sub (38) */
case 38:
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    JS_SP2->u.vinteger -= JS_SP1->u.vinteger;
} else {
    JSNode l_cvt, r_cvt;
    JSNode *l, *r;

    if (JS_IS_NUMBER(JS_SP2))
        l = JS_SP2;
    else {
        js_vm_to_number(vm, JS_SP2, &l_cvt);
        l = &l_cvt;
    }

    if (JS_IS_NUMBER(JS_SP1))
        r = JS_SP1;
    else {
        js_vm_to_number(vm, JS_SP1, &r_cvt);
        r = &r_cvt;
    }

    if (l->type == JS_NAN || r->type == JS_NAN)
        JS_SP2->type = JS_NAN;
    else if (l->type == JS_INTEGER) {
        if (r->type == JS_INTEGER) {
            JS_SP2->type = JS_INTEGER;
            JS_SP2->u.vinteger = l->u.vinteger - r->u.vinteger;
        } else {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = (JSFloat) l->u.vinteger - r->u.vfloat;
        }
    } else {
        if (r->type == JS_INTEGER) {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = l->u.vfloat - (JSFloat) r->u.vinteger;
        } else {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = l->u.vfloat - r->u.vfloat;
        }
    }
}

JS_POP();
break;

/* operand add (39) */
case 39:
if (JS_SP2->type == JS_STRING || JS_SP1->type == JS_STRING) {
    unsigned char *d2, *d1, *ndata;
    unsigned int d2_len, d1_len, nlen;
    JSNode cvt;

    if (JS_SP2->type == JS_STRING) {
        d2 = JS_SP2->u.vstring->data;
        d2_len = JS_SP2->u.vstring->len;
    } else {
        js_vm_to_string(vm, JS_SP2, &cvt);
        d2 = cvt.u.vstring->data;
        d2_len = cvt.u.vstring->len;
    }
    if (JS_SP1->type == JS_STRING) {
        d1 = JS_SP1->u.vstring->data;
        d1_len = JS_SP1->u.vstring->len;
    } else {
        js_vm_to_string(vm, JS_SP1, &cvt);
        d1 = cvt.u.vstring->data;
        d1_len = cvt.u.vstring->len;
    }

    nlen = d2_len + d1_len;
    ndata = js_vm_alloc(vm, nlen);
    memcpy(ndata, d2, d2_len);
    memcpy(ndata + d2_len, d1, d1_len);

    js_vm_make_static_string(vm, JS_SP2, ndata, nlen);
    JS_SP2->u.vstring->staticp = 0;
    JS_POP();
    JS_MAYBE_GC();
} else if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    JS_SP2->u.vinteger += JS_SP1->u.vinteger;
    JS_POP();
} else {
    JSNode l_cvt, r_cvt;
    JSNode *l, *r;

    if (JS_IS_NUMBER(JS_SP2))
        l = JS_SP2;
    else {
        js_vm_to_number(vm, JS_SP2, &l_cvt);
        l = &l_cvt;
    }

    if (JS_IS_NUMBER(JS_SP1))
        r = JS_SP1;
    else {
        js_vm_to_number(vm, JS_SP1, &r_cvt);
        r = &r_cvt;
    }

    if (l->type == JS_NAN || r->type == JS_NAN)
        JS_SP2->type = JS_NAN;
    else if (l->type == JS_INTEGER) {
        if (r->type == JS_INTEGER) {
            JS_SP2->type = JS_INTEGER;
            JS_SP2->u.vinteger = l->u.vinteger + r->u.vinteger;
        } else {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = (JSFloat) l->u.vinteger + r->u.vfloat;
        }
    } else {
        if (r->type == JS_INTEGER) {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = l->u.vfloat + (JSFloat) r->u.vinteger;
        } else {
            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = l->u.vfloat + r->u.vfloat;
        }
    }

    JS_POP();
}

break;

/* operand mul (40) */
case 40:
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    JS_SP2->u.vinteger *= JS_SP1->u.vinteger;
} else {
    JSNode l_cvt, r_cvt;
    JSNode *l, *r;

    if (JS_IS_NUMBER(JS_SP2))
        l = JS_SP2;
    else {
        js_vm_to_number(vm, JS_SP2, &l_cvt);
        l = &l_cvt;
    }

    if (JS_IS_NUMBER(JS_SP1))
        r = JS_SP1;
    else {
        js_vm_to_number(vm, JS_SP1, &r_cvt);
        r = &r_cvt;
    }

    if (l->type == JS_NAN || r->type == JS_NAN)
        JS_SP2->type = JS_NAN;
    else if (l->type == JS_INTEGER) {
        if (r->type == JS_INTEGER) {
            JS_SP2->type = JS_INTEGER;
            JS_SP2->u.vinteger = l->u.vinteger * r->u.vinteger;
        } else {
            if (l->u.vinteger == 0 && (JS_IS_POSITIVE_INFINITY(r)
                                       || JS_IS_NEGATIVE_INFINITY(r)))
                JS_SP2->type = JS_NAN;
            else {
                JS_SP2->type = JS_FLOAT;
                JS_SP2->u.vfloat = (JSFloat) l->u.vinteger * r->u.vfloat;
            }
        }
    } else {
        if ((JS_IS_POSITIVE_INFINITY(l) || JS_IS_NEGATIVE_INFINITY(l))
            && ((r->type == JS_INTEGER && r->u.vinteger == 0)
                || (r->type == JS_FLOAT && r->u.vfloat == 0.0)))
            JS_SP2->type = JS_NAN;
        else {
            JS_SP2->type = JS_FLOAT;

            if (r->type == JS_INTEGER)
                JS_SP2->u.vfloat = l->u.vfloat * (JSFloat) r->u.vinteger;
            else
                JS_SP2->u.vfloat = l->u.vfloat * r->u.vfloat;
        }
    }
}

JS_POP();
break;

/* operand div (41) */
case 41:
{
    int nan = 0;
    JSFloat l = 0, r =0;
    int l_inf = 0;
    int r_inf = 0;
    JSNode *n;
    JSNode cvt;

    /* Convert divident to float. */
    if (JS_IS_NUMBER(JS_SP2))
        n = JS_SP2;
    else {
        js_vm_to_number(vm, JS_SP2, &cvt);
        n = &cvt;
    }

    switch (n->type) {
    case JS_INTEGER:
        l = (JSFloat) n->u.vinteger;
        break;

    case JS_FLOAT:
        l = n->u.vfloat;
        if (JS_IS_POSITIVE_INFINITY(n) || JS_IS_NEGATIVE_INFINITY(n))
            l_inf = 1;
        break;

    case JS_NAN:
    default:
        nan = 1;
        break;
    }

    /* Convert divisor to float. */
    if (JS_IS_NUMBER(JS_SP1))
        n = JS_SP1;
    else {
        js_vm_to_number(vm, JS_SP2, &cvt);
        n = &cvt;
    }

    switch (n->type) {
    case JS_INTEGER:
        r = (JSFloat) n->u.vinteger;
        break;

    case JS_FLOAT:
        r = n->u.vfloat;
        if (JS_IS_POSITIVE_INFINITY(n) || JS_IS_NEGATIVE_INFINITY(n))
            r_inf = 1;
        break;

    case JS_NAN:
    default:
        nan = 1;
        break;
    }

    /* Do the division. */
    JS_POP();
    if (nan || (l_inf && r_inf))
        JS_SP1->type = JS_NAN;
    else {
        if (l_inf && r == 0.0) {
            /* <l> is already an infinity. */
            JS_SP1->type = JS_FLOAT;
            JS_SP1->u.vfloat = l;
        } else if (l == 0.0 && r == 0.0)
            JS_SP1->type = JS_NAN;
        else {
            JS_SP1->type = JS_FLOAT;
            JS_SP1->u.vfloat = l / r;
        }
    }
}

break;

/* operand mod (42) */
case 42:
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    if (JS_SP1->u.vinteger == 0)
        JS_SP2->type = JS_NAN;
    else
        JS_SP2->u.vinteger %= JS_SP1->u.vinteger;
} else {
    JSNode l_cvt, r_cvt;
    JSNode *l, *r;

    if (JS_IS_NUMBER(JS_SP2))
        l = JS_SP2;
    else {
        js_vm_to_number(vm, JS_SP2, &l_cvt);
        l = &l_cvt;
    }

    if (JS_IS_NUMBER(JS_SP1))
        r = JS_SP1;
    else {
        js_vm_to_number(vm, JS_SP1, &r_cvt);
        r = &r_cvt;
    }

    if (l->type == JS_NAN || r->type == JS_NAN)
        JS_SP2->type = JS_NAN;
    else if (JS_IS_POSITIVE_INFINITY(l)
             || JS_IS_NEGATIVE_INFINITY(l)
             || ((r->type == JS_INTEGER && r->u.vinteger == 0)
                 || (r->type == JS_FLOAT && r->u.vfloat == 0.0)))
        JS_SP2->type = JS_NAN;
    else if (JS_IS_POSITIVE_INFINITY(r)
             || JS_IS_NEGATIVE_INFINITY(r))
        JS_COPY(JS_SP2, l);
    else if ((l->type == JS_INTEGER && l->u.vinteger == 0)
             || (l->type == JS_FLOAT && l->u.vfloat == 0.0))
        JS_COPY(JS_SP2, l);
    else {
        if (l->type == JS_INTEGER && r->type == JS_INTEGER) {
            JS_SP2->type = JS_INTEGER;
            JS_SP2->u.vinteger = l->u.vinteger % r->u.vinteger;
        } else {
            JSFloat ld, rd;
            int full;

            if (l->type == JS_INTEGER)
                ld = (JSFloat) l->u.vinteger;
            else
                ld = l->u.vfloat;

            if (r->type == JS_INTEGER)
                rd = (JSFloat) r->u.vinteger;
            else
                rd = r->u.vfloat;

            full = ld / rd;

            JS_SP2->type = JS_FLOAT;
            JS_SP2->u.vfloat = ld - (full * rd);
        }
    }
}

JS_POP();
break;

/* operand neg (43) */
case 43:
if (JS_SP1->type == JS_INTEGER)
    JS_SP1->u.vinteger = -JS_SP1->u.vinteger;
else if (JS_SP1->type == JS_FLOAT)
    JS_SP1->u.vfloat = -JS_SP1->u.vfloat;
else if (JS_SP1->type == JS_NAN);
else {
    JSNode cvt;

    js_vm_to_number(vm, JS_SP1, &cvt);

    JS_SP1->type = cvt.type;
    switch (cvt.type) {
    case JS_INTEGER:
        JS_SP1->u.vinteger = -cvt.u.vinteger;
        break;

    case JS_FLOAT:
        JS_SP1->u.vfloat = -cvt.u.vfloat;
        break;

    case JS_NAN:
    default:
        /* Nothing here. */
        break;
    }
}

break;

/* operand and (44) */
case 44:
JS_OPERAND_BINARY(&);
break;

/* operand not (45) */
case 45:
JS_SP1->u.vboolean = JS_IS_FALSE(JS_SP1);
JS_SP1->type = JS_BOOLEAN;
break;

/* operand or (46) */
case 46:
JS_OPERAND_BINARY(|);
break;

/* operand xor (47) */
case 47:
JS_OPERAND_BINARY(^);
break;

/* operand shift_left (48) */
case 48:
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    JS_SP2->u.vinteger = ((JSInt32) JS_SP2->u.vinteger
                          << (JSUInt32) JS_SP1->u.vinteger);
    JS_POP();
} else {
    JSInt32 l;
    JSUInt32 r;

    l = js_vm_to_int32(vm, JS_SP2);
    r = (JSUInt32) js_vm_to_int32(vm, JS_SP1);

    JS_SP2->u.vinteger = l << r;
    JS_SP2->type = JS_INTEGER;
    JS_POP();
}

break;

/* operand shift_right (49) */
case 49:
if (JS_SP2->type == JS_INTEGER && JS_SP1->type == JS_INTEGER) {
    JS_SP2->u.vinteger = ((JSInt32) JS_SP2->u.vinteger
                          >> (JSUInt32) JS_SP1->u.vinteger);
    JS_POP();
} else {
    JSInt32 l;
    JSUInt32 r;

    l = js_vm_to_int32(vm, JS_SP2);
    r = (JSUInt32) js_vm_to_int32(vm, JS_SP1);

    JS_SP2->u.vinteger = l >> r;
    JS_SP2->type = JS_INTEGER;
    JS_POP();
}

break;

/* operand shift_rright (50) */
case 50:
{
    JSInt32 l;
    JSUInt32 r;

    l = js_vm_to_int32(vm, JS_SP2);
    r = (JSUInt32) js_vm_to_int32(vm, JS_SP1);

    if (r > 0)
        JS_SP2->u.vinteger = (l & 0x7fffffff) >> r;
    else
        JS_SP2->u.vinteger = l;

    JS_SP2->type = JS_INTEGER;
    JS_POP();
}

break;

/* operand iffalse (51) */
case 51:
READ_INT32(i);
if (JS_IS_FALSE(JS_SP1))
    SETPC_RELATIVE(i);
JS_POP();
break;

/* operand iftrue (52) */
case 52:
READ_INT32(i);
if (JS_IS_TRUE(JS_SP1))
    SETPC_RELATIVE(i);
JS_POP();
break;

/* operand call_method (53) */
case 53:
  /* Fetch the method symbol. */
READ_INT32(j);

if (JS_SP1->type == JS_BUILTIN) {
    JS_SAVE_REGS();
    if (JS_SP1->u.vbuiltin->info->method_proc) {
        if ((*JS_SP1->u.vbuiltin->info->method_proc) (vm,
                                                      JS_SP1->u.vbuiltin->
                                                      info,
                                                      JS_SP1->u.vbuiltin->
                                                      instance_context, j,
                                                      &builtin_result,
                                                      JS_SP2)
            == JS_PROPERTY_UNKNOWN) {
            ERROR("call_method: unknown method");
		}
    } else {
        ERROR("illegal builtin object for call_method");
	}

    JS_COPY(JS_SP0, &builtin_result);
    JS_PUSH();
    JS_MAYBE_GC();
} else if (JS_SP1->type == JS_OBJECT) {
    JSNode method;

    if (js_vm_object_load_property(vm, JS_SP1->u.vobject, j, &method)
        == JS_PROPERTY_FOUND) {
        /* The property has been defined in the object. */

        if (method.type != JS_FUNC) {
            ERROR("call_method: unknown method");
		}

        /* And once again.  We must do a subroutine call here. */
        JS_SUBROUTINE_CALL(method.u.vfunction->implementation);
    } else
        /* Let our prototype handle this. */
        goto _op_call_method_try_proto;
} else if (vm->prim[JS_SP1->type]) {
    /* The primitive language types. */
  _op_call_method_try_proto:
    JS_SAVE_REGS();
    if ((*vm->prim[JS_SP1->type]->method_proc) (vm, vm->prim[JS_SP1->type],
                                                JS_SP1, j, &builtin_result,
                                                JS_SP2)
        == JS_PROPERTY_UNKNOWN) {
        JSNode method;
        int result = JS_PROPERTY_UNKNOWN;

        /* Let's see if we can find it from the prototype. */
        if (JS_SP1->type == JS_STRING && JS_SP1->u.vstring->prototype)
            result = js_vm_object_load_property(vm,
                                                JS_SP1->u.vstring->
                                                prototype, j, &method);
        else if (JS_SP1->type == JS_ARRAY && JS_SP1->u.varray->prototype)
            result = js_vm_object_load_property(vm,
                                                JS_SP1->u.varray->
                                                prototype, j, &method);
        else if (JS_SP1->type == JS_FUNC && JS_SP1->u.vfunction->prototype)
            result
                =
                js_vm_object_load_property(vm,
                                           JS_SP1->u.vfunction->prototype,
                                           j, &method);

        if (result == JS_PROPERTY_UNKNOWN || method.type != JS_FUNC) {
            ERROR("call_method: unknown method");
		}
        /* Do the subroutine call. */
        JS_SUBROUTINE_CALL(method.u.vfunction->implementation);
    } else {
        JS_COPY(JS_SP0, &builtin_result);
        JS_PUSH();
        JS_MAYBE_GC();
    }
} else {
    ERROR("illegal object for call_method");
}
break;

/* operand jmp (54) */
case 54:
READ_INT32(i);
SETPC_RELATIVE(i);
break;

/* operand jsr (55) */
case 55:
  /* Call the global method. */
{
    JSNode f;

    /* Fetch the function to our local variable. */
    JS_COPY(&f, JS_SP1);
    function = &f;

    /* Reset the `this' to null. */
    JS_SP1->type = JS_NULL;

    if (function->type == JS_BUILTIN
        && function->u.vbuiltin->info->global_method_proc) {
        JS_SAVE_REGS();
        (*function->u.vbuiltin->info->global_method_proc) (vm,
                                                           function->u.
                                                           vbuiltin->info,
                                                           function->u.
                                                           vbuiltin->
                                                           instance_context,
                                                           &builtin_result,
                                                           JS_SP2);

        JS_COPY(JS_SP0, &builtin_result);
        JS_PUSH();
		JS_MAYBE_GC();
    } else if (function->type == JS_FUNC) {
        JS_SUBROUTINE_CALL(function->u.vfunction->implementation);
    } else {
        ERROR("illegal function object in jsr");
    }
}

break;

/* operand return (56) */
case 56:
if (fp->u.iptr == NULL)
    /* Return from the global scope. */
    DONE();

  /* STACKFRAME */

  /* Check if the stack has been modified by min_args. */
if (JS_ARGS_FIXP->u.args_fix.delta) {
    unsigned int delta = JS_ARGS_FIXP->u.args_fix.delta;

    /*
     * Yes it was.  Truncate it back to the state where it was
     * before the call.
     */

    memmove(JS_SP1 + delta, JS_SP1,
            (fp - JS_SP0 + JS_ARGS_FIXP->u.args_fix.argc)
            * sizeof(JSNode));

    sp += delta;
    fp += delta;
}

  /* Set pc to the saved return address. */
#if 0
if (fp[-3].type != JS_IPTR) {
    ERROR("can't find saved return address");
}
#endif
pc = fp[-3].u.iptr;

{
    void *old_fp;

    /* Save old frame pointer. */
#if 0
    if (fp->type != JS_IPTR) {
        ERROR("can't find saved frame pointer");
	}
#endif
    old_fp = fp->u.iptr;

    /* Put return value to its correct location. */
    JS_COPY(fp, JS_SP1);

    /* Restore sp. */
    sp = &fp[-1];

    /* Restore frame pointer. */
    fp = old_fp;
}

break;

/* operand typeof (57) */
case 57:
{
    char *typeof_name = "";     /* Initialized to make compiler quiet. */

    switch (JS_SP1->type) {
    case JS_UNDEFINED:
        typeof_name = "undefined";
        break;

    case JS_NULL:
        typeof_name = "object";
        break;

    case JS_BOOLEAN:
        typeof_name = "boolean";
        break;

    case JS_INTEGER:
    case JS_FLOAT:
    case JS_NAN:
        typeof_name = "number";
        break;

    case JS_STRING:
        typeof_name = "string";
        break;

    case JS_ARRAY:
        typeof_name = "#array";
        break;

    case JS_OBJECT:
        typeof_name = "object";
        break;

    case JS_SYMBOL:
        typeof_name = "#symbol";
        break;

    case JS_BUILTIN:
        typeof_name = "#builtin";
        break;

    case JS_FUNC:
        typeof_name = "function";
        break;

    case JS_IPTR:
        typeof_name = "#iptr";
        break;

    case JS_ARGS_FIX:
        typeof_name = "#argsfix";
        break;
    }

    js_vm_make_static_string(vm, JS_SP1, typeof_name, strlen(typeof_name));
    JS_MAYBE_GC();
}

break;

/* operand new (58) */
case 58:
  /* Check object. */
if (JS_SP1->type == JS_BUILTIN && JS_SP1->u.vbuiltin->info->new_proc) {
    JS_SAVE_REGS();
    (*JS_SP1->u.vbuiltin->info->new_proc) (vm, JS_SP1->u.vbuiltin->info,
                                           JS_SP2, JS_SP1);

    /* Push a dummy return value for the constructor.  This is ignored. */
    JS_SP0->type = JS_UNDEFINED;
    JS_PUSH();
} else if (JS_SP1->type == JS_FUNC) {
    JSObject *obj;
    JSNode f;
    JSNode prototype;

    /* The prototype is an object. */
    prototype.type = JS_OBJECT;

    /* Create the prototype for the function, if it is not defined. */
    if (JS_SP1->u.vfunction->prototype == NULL) {
        JS_SP1->u.vfunction->prototype = js_vm_object_new(vm);

        /* Set its __proto__ to point to Object's prototype.  */
        prototype.u.vobject = vm->prim[JS_OBJECT]->prototype;
        js_vm_object_store_property(vm, JS_SP1->u.vfunction->prototype,
                                    vm->syms.s___proto__, &prototype);
    }

    /* Allocate a new object and set its prototype. */

    obj = js_vm_object_new(vm);

    prototype.u.vobject = JS_SP1->u.vfunction->prototype;
    js_vm_object_store_property(vm, obj, vm->syms.s___proto__, &prototype);

    /*
     * Basicly we do a jsr to the function given in JS_SP1.  But first,
     * we must set `this' pointer to the correct value.  See `jsr' for
     * the details.
     */
    JS_COPY(&f, JS_SP1);

    /* Replace func with the new object. */
    JS_SP1->type = JS_OBJECT;
    JS_SP1->u.vobject = obj;

    JS_SUBROUTINE_CALL(f.u.vfunction->implementation);
}
  /* The primitive language types. */
else if (vm->prim[JS_SP1->type]) {
    JS_SAVE_REGS();
    (*vm->prim[JS_SP1->type]->new_proc) (vm, vm->prim[JS_SP1->type],
                                         JS_SP2, JS_SP1);
    JS_PUSH();
} else {
    ERROR("illegal object for new");
}

JS_MAYBE_GC();
break;

/* operand delete_property (59) */
case 59:
  /* Fetch the property symbol. */
READ_INT32(j);

if (JS_SP1->type == JS_BUILTIN) {
    /*
     * XXX It should be possible to apply delete operand to builtin
     * XXX objects.
     */
    ERROR("delete_property: JS_BUILTIN: not implemented yet");
} else if (JS_SP1->type == JS_OBJECT) {
    js_vm_object_delete_property(vm, JS_SP1->u.vobject, j);
} else if (JS_SP1->type == JS_NULL) {
    /* Delete a property from an object in the with-chain. */
    /* WITHCHAIN */
    ERROR
        ("delete_property: not implemented yet for the with-chain objects");
}
  /* The primitive language types. */
  /*
   * XXX Since we can't delete properties from builtins, we can't delete
   * XXX them from the primitive language types.
   */
else
    ERROR("illegal object for delete_property");

  /* The delete operand returns an undefined value. */
JS_SP1->type = JS_UNDEFINED;
break;

/* operand delete_array (60) */
case 60:
if (JS_SP2->type == JS_BUILTIN) {
    ERROR("delete_array: JS_BUILTIN: not implemented yet");
} else if (JS_SP2->type == JS_OBJECT) {
    js_vm_object_delete_array(vm, JS_SP2->u.vobject, JS_SP1);
    JS_POP();
} else if (JS_SP2->type == JS_ARRAY) {
    if (JS_SP1->type == JS_INTEGER) {
        if (0 <= JS_SP1->u.vinteger
            && JS_SP1->u.vinteger < JS_SP2->u.varray->length)
            JS_SP2->u.varray->data[JS_SP1->u.vinteger].type = JS_UNDEFINED;
        JS_POP();
    } else {
        ERROR("illegal array index in delete_array");
	}
} else {
    ERROR("illegal object for delete_array");
}

  /* The delete operand returns an undefined value. */
JS_SP1->type = JS_UNDEFINED;
break;

/* operand locals (61) */
case 61:
READ_INT16(i);
if (sp - i - JS_RESERVE_STACK_FOR_FUNCTION < vm->stack) {
    ERROR("stack overflow");
}

for (; i > 0; i--) {
    JS_SP0->type = JS_UNDEFINED;
    JS_PUSH();
}

break;

/* operand min_args (62) */
case 62:
READ_INT8(i);

if (JS_SP1->u.vinteger < i) {
    unsigned int delta = i - JS_SP1->u.vinteger;
    unsigned int argc = JS_SP1->u.vinteger;

    memmove(JS_SP1 - delta, JS_SP1, (fp - JS_SP0 + argc) * sizeof(JSNode));
    sp -= delta;
    fp -= delta;

    /* Fill up the fix_args slot. */
    JS_ARGS_FIXP->u.args_fix.argc = argc;
    JS_ARGS_FIXP->u.args_fix.delta = delta;

    for (; argc < i; argc++)
        JS_ARG(argc)->type = JS_UNDEFINED;
}

JS_POP();
break;

/* operand load_nth_arg (63) */
case 63:
{
    int index = JS_SP1->u.vinteger;
    JS_COPY(JS_SP1, JS_ARG(index));
}

break;

/* operand with_push (64) */
case 64:
if (JS_SP1->type != JS_OBJECT && JS_SP1->type != JS_BUILTIN) {
    ERROR("illegal object for with_push");
}
  /* WITHCHAIN */

if (JS_WITHPTR->u.iptr == NULL) {
    JSNode *np;
    JSUIntAlign *ip = js_vm_alloc(vm,
                                  sizeof(JSUIntAlign)
                                  + sizeof(JSNode));
    *ip = 1;
    np = (JSNode *) ((unsigned char *) ip + sizeof(JSUIntAlign));

    JS_COPY(np, JS_SP1);
    JS_WITHPTR->u.iptr = ip;
} else {
    JSNode *np;
    JSUIntAlign *ip = JS_WITHPTR->u.iptr;
    JSUIntAlign ui = *ip;

    ip = js_vm_realloc(vm, ip, sizeof(JSUIntAlign)
                       + ((ui + 1) * sizeof(JSNode)));
    (*ip)++;
    np = (JSNode *) ((unsigned char *) ip + sizeof(JSUIntAlign));

    JS_COPY(&np[ui], JS_SP1);
    JS_WITHPTR->u.iptr = ip;
}

JS_POP();
break;

/* operand with_pop (65) */
case 65:
READ_INT8(i);

  /* WITHCHAIN */

{
    JSUIntAlign *ip = JS_WITHPTR->u.iptr;

    if (ip == NULL || *ip < i) {
        ERROR("with stack underflow in with_pop");
	}
    *ip -= i;
}

break;

/* operand try_push (66) */
case 66:
READ_INT32(i);

{
    JSErrorHandlerFrame *frame = js_calloc(vm, 1, sizeof(*frame));

    frame->next = vm->error_handler;
    frame->sp = sp;
    frame->fp = fp;
    frame->pc = pc;
    frame->pc_delta = i;
    vm->error_handler = frame;

    if (setjmp(vm->error_handler->error_jmp)) {
        /* Ok, we caught an error. */

        /* Restore our state. */
        sp = vm->error_handler->sp;
        fp = vm->error_handler->fp;
        pc = vm->error_handler->pc;
        i = vm->error_handler->pc_delta;

        /* Push the thrown value to the stack. */
        JS_COPY(JS_SP0, &vm->error_handler->thrown);
        JS_PUSH();

        /* Remove this handler frame. */
        frame = vm->error_handler;
        vm->error_handler = vm->error_handler->next;
        js_free(frame);

        /* Do the jump to the catch block. */
        SETPC_RELATIVE(i);
    }
}

break;

/* operand try_pop (67) */
case 67:
READ_INT8(i);

for (; i > 0; i--) {
    JSErrorHandlerFrame *frame = vm->error_handler;

    vm->error_handler = vm->error_handler->next;
    js_free(frame);
}

break;

/* operand throw (68) */
case 68:
{
    JSErrorHandlerFrame *f = vm->error_handler;

    if (f->sp == NULL) {
#ifdef JS_RUNTIME_WARNING  
        JSNode cvt;
        int len;

        /*
         * We are jumping to the C-toplevel.  Convert our thrown value
         * to string and store it to the vm->error.
         */
        js_vm_to_string(vm, JS_SP1, &cvt);

        len = cvt.u.vstring->len;
        if (len + 1 > sizeof(vm->error))
            len = sizeof(vm->error) - 1;

        memcpy(vm->error, cvt.u.vstring->data, len);
        vm->error[len] = '\0';
#endif
    } else
        JS_COPY(&f->thrown, JS_SP1);

    longjmp(f->error_jmp, 1);

    /* NOTREACHED (I hope). */
#ifdef JS_RUNTIME_WARNING  
    sprintf(buf, "VM: no valid error handler initialized%s",
            JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
	js_iostream_write(vm->s_stderr, buf, strlen(buf));
    js_iostream_flush(vm->s_stderr);
#else
	fwrite(buf, strlen(buf), 1, stderr);
#endif
#endif

    abort();
}

break;

/* operand iffalse_b (69) */
case 69:
READ_INT32(i);
if (!JS_SP1->u.vboolean)
    SETPC_RELATIVE(i);
JS_POP();
break;

/* operand iftrue_b (70) */
case 70:
READ_INT32(i);
if (JS_SP1->u.vboolean)
    SETPC_RELATIVE(i);
JS_POP();
break;

/* operand add_1_i (71) */
case 71:
JS_SP1->u.vinteger++;
break;

/* operand add_2_i (72) */
case 72:
JS_SP1->u.vinteger += 2;
break;

/* operand load_global_w (73) */
case 73:
READ_INT32(j);
{
    int found = 0;

    /* Loop over the with chain. */
    /* WITHCHAIN */
    if (JS_WITHPTR->u.iptr) {
        JSUIntAlign *uip = JS_WITHPTR->u.iptr;
        JSUIntAlign ui = *uip;
        JSNode *wp = (JSNode *) ((unsigned char *) uip
                                 + sizeof(JSUIntAlign));

        for (i = 0; i < ui; i++) {
            JSNode *w = &wp[i];
            int result = JS_PROPERTY_UNKNOWN;

            if (w->type == JS_BUILTIN) {
                JS_SAVE_REGS();
                if (w->u.vbuiltin->info->property_proc)
                    result = (*w->u.vbuiltin->info->property_proc) (vm,
                                                                    w->u.
                                                                    vbuiltin->
                                                                    info,
                                                                    w->u.
                                                                    vbuiltin->
                                                                    instance_context,
                                                                    j, 0,
                                                                    &builtin_result);
            } else if (w->type == JS_OBJECT) {
                result = js_vm_object_load_property(vm, w->u.vobject, j,
                                                    &builtin_result);
            } else {
                ERROR("corrupted with-chain in load_global");
			}
            if (result == JS_PROPERTY_FOUND) {
                JS_COPY(JS_SP0, &builtin_result);
                JS_PUSH();
                found = 1;
                break;
            }
        }
    }

    if (!found) {
        /* Use the global value. */
        JS_COPY(JS_SP0, JS_GLOBAL(j));
        JS_PUSH();
#ifdef JS_RUNTIME_WARNING  
        if (vm->warn_undef && JS_SP1->type == JS_UNDEFINED) {
            sprintf(buf, "VM: warning: using undefined global `%s'%s",
                    js_vm_symname(vm, j), JS_HOST_LINE_BREAK);
#ifdef JS_IOSTREAM
			js_iostream_write(vm->s_stderr, buf, strlen(buf));
#else
			fwrite(buf, strlen(buf), 1, stderr);
#endif
        }
#endif
    }
}

break;

/* operand jsr_w (74) */
case 74:
  /* Read the subroutine symbol index. */
READ_INT32(j);

{
    int found = 0;

    /* Loop over the with-chain. */
    /* WITHCHAIN */
    if (JS_WITHPTR->u.iptr) {
        JSUIntAlign *uip = JS_WITHPTR->u.iptr;
        JSUIntAlign ui = *uip;
        JSNode *wp = (JSNode *) ((unsigned char *) uip
                                 + sizeof(JSUIntAlign));

        for (i = 0; i < ui; i++) {
            JSNode *w = &wp[i];
            int result = JS_PROPERTY_UNKNOWN;

            if (w->type == JS_BUILTIN) {
                JS_SAVE_REGS();
                if (w->u.vbuiltin->info->method_proc)
                    result = (*w->u.vbuiltin->info->method_proc) (vm,
                                                                  w->u.
                                                                  vbuiltin->
                                                                  info,
                                                                  w->u.
                                                                  vbuiltin->
                                                                  instance_context,
                                                                  j,
                                                                  &builtin_result,
                                                                  JS_SP2);
                JS_MAYBE_GC();

                if (result == JS_PROPERTY_FOUND) {
                    JS_COPY(JS_SP0, &builtin_result);
                    JS_PUSH();
                }
            } else if (w->type == JS_OBJECT) {
                JSNode method;

                js_vm_object_load_property(vm, w->u.vobject, j, &method);
                if (method.type == JS_FUNC) {
                    result = JS_PROPERTY_FOUND;

                    /* The object defines the method.  Do a subroutine call. */

                    /* First: replace the null `this' with `w'. */
                    JS_COPY(JS_SP1, w);

                    /* Then, do the normal subroutine call. */
                    JS_SUBROUTINE_CALL(method.u.vfunction->implementation);
                }
            } else {
                ERROR("corrupted with-chain in jsr_w");
			}
            if (result == JS_PROPERTY_FOUND) {
                found = 1;
                break;
            }
        }
    }

    if (!found) {
        JSNode f;

        /* Call the global method. */
        JS_COPY(&f, JS_SP1);
        function = &f;

        /* Reset the `this' to null. */
        JS_SP1->type = JS_NULL;

        if (function->type == JS_BUILTIN
            && function->u.vbuiltin->info->global_method_proc) {
            JS_SAVE_REGS();
            (*function->u.vbuiltin->info->global_method_proc) (vm,
                                                               function->u.
                                                               vbuiltin->
                                                               info,
                                                               function->u.
                                                               vbuiltin->
                                                               instance_context,
                                                               &builtin_result,
                                                               JS_SP2);

            JS_COPY(JS_SP0, &builtin_result);
            JS_PUSH();
        } else if (function->type == JS_FUNC) {
            JS_SUBROUTINE_CALL(function->u.vfunction->implementation);
        } else {
            ERROR("symbol `%s' is undefined as function", js_vm_symname(vm, j));
        }
    }
}

break;
